package com.example.demo.graph;

import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.KeyStrategy;
import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.StateGraph;
import com.alibaba.cloud.ai.graph.action.AsyncEdgeAction;
import com.alibaba.cloud.ai.graph.action.AsyncNodeAction;
import com.alibaba.cloud.ai.graph.exception.GraphStateException;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.List;

import static com.alibaba.cloud.ai.graph.StateGraph.END;
import static com.alibaba.cloud.ai.graph.StateGraph.START;

import com.alibaba.cloud.ai.graph.node.code.CodeExecutorNodeAction;
import com.alibaba.cloud.ai.graph.node.code.entity.CodeExecutionConfig;
import com.alibaba.cloud.ai.graph.node.code.CodeExecutor;
import com.alibaba.cloud.ai.graph.node.code.LocalCommandlineCodeExecutor;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;

import com.alibaba.cloud.ai.graph.node.AnswerNode;
import com.alibaba.cloud.ai.graph.node.KnowledgeRetrievalNode;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.ai.document.Document;
import com.alibaba.cloud.ai.graph.node.AssignerNode;
import com.alibaba.cloud.ai.graph.node.HttpNode;
import org.springframework.http.HttpMethod;
import com.alibaba.cloud.ai.graph.node.QuestionClassifierNode;

import static com.alibaba.cloud.ai.graph.action.AsyncEdgeAction.edge_async;

import com.alibaba.cloud.ai.graph.node.LlmNode;
import org.springframework.ai.chat.messages.AssistantMessage;
import com.alibaba.cloud.ai.graph.node.BranchNode;

@Component
public class GraphBuilder {
    // todo: add your knowledge base
    @Value("${rag.source:classpath:/data/}")
    private Resource ragSource;

    @Value("${app.api.base-url}")
    private String baseUrl;

    @Bean
    public CompiledGraph buildGraph(
            ChatModel chatModel
            , VectorStore vectorStore
            , CodeExecutionConfig codeExecutionConfig, CodeExecutor codeExecutor
    ) throws Exception {
        ChatClient chatClient = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor()).build();

        // new stateGraph
        // todo: Add some non-node variable names, such as sys and conversation variables. Format as sys_xxx.
        StateGraph stateGraph = new StateGraph(() -> {
            Map<String, KeyStrategy> strategies = new HashMap<>();
            strategies.put("sys_query", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode2_result", (o1, o2) -> o2);
            strategies.put("LLMNode5_text", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode3_result", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode1_result", (o1, o2) -> o2);
            strategies.put("httpNode9_status_code", (o1, o2) -> o2);
            strategies.put("codeNode19_stopHosting", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode4_result", (o1, o2) -> o2);
            strategies.put("codeNode18_result", (o1, o2) -> o2);
            strategies.put("httpNode9_files", (o1, o2) -> o2);
            strategies.put("httpNode6_status_code", (o1, o2) -> o2);
            strategies.put("codeNode1_character_design", (o1, o2) -> o2);
            strategies.put("codeNode3_general_rules", (o1, o2) -> o2);
            strategies.put("httpNode6_files", (o1, o2) -> o2);
            strategies.put("startNode1_lessee", (o1, o2) -> o2);
            strategies.put("httpNode7_status_code", (o1, o2) -> o2);
            strategies.put("codeNode6_customer_analysis_str", (o1, o2) -> o2);
            strategies.put("httpNode8_status_code", (o1, o2) -> o2);
            strategies.put("codeNode3_general_rules_str", (o1, o2) -> o2);
            strategies.put("httpNode9_headers", (o1, o2) -> o2);
            strategies.put("LLMNode13_text", (o1, o2) -> o2);
            strategies.put("httpNode3_body", (o1, o2) -> o2);
            strategies.put("httpNode3_files", (o1, o2) -> o2);
            strategies.put("LLMNode6_text", (o1, o2) -> o2);
            strategies.put("LLMNode15_text", (o1, o2) -> o2);
            strategies.put("httpNode5_body", (o1, o2) -> o2);
            strategies.put("httpNode2_body", (o1, o2) -> o2);
            strategies.put("httpNode6_headers", (o1, o2) -> o2);
            strategies.put("image_analysis", (o1, o2) -> o2);
            strategies.put("LLMNode12_text", (o1, o2) -> o2);
            strategies.put("httpNode2_headers", (o1, o2) -> o2);
            strategies.put("startNode1_message_id", (o1, o2) -> o2);
            strategies.put("codeNode13_result", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode9_result", (o1, o2) -> o2);
            strategies.put("httpNode1_files", (o1, o2) -> o2);
            strategies.put("codeNode22_result", (o1, o2) -> o2);
            strategies.put("codeNode20_result", (o1, o2) -> o2);
            strategies.put("httpNode3_status_code", (o1, o2) -> o2);
            strategies.put("httpNode1_status_code", (o1, o2) -> o2);
            strategies.put("codeNode15_result", (o1, o2) -> o2);
            strategies.put("codeNode2_special_scenarios_str", (o1, o2) -> o2);
            strategies.put("codeNode26_quotableProductNames", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode7_result", (o1, o2) -> o2);
            strategies.put("codeNode11_result", (o1, o2) -> o2);
            strategies.put("codeNode4_product_names_list", (o1, o2) -> o2);
            strategies.put("httpNode2_status_code", (o1, o2) -> o2);
            strategies.put("baojia", (o1, o2) -> o2);
            strategies.put("codeNode17_result", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode5_result", (o1, o2) -> o2);
            strategies.put("codeNode6_custom_info", (o1, o2) -> o2);
            strategies.put("httpNode5_status_code", (o1, o2) -> o2);
            strategies.put("httpNode4_status_code", (o1, o2) -> o2);
            strategies.put("startNode1_server_conversation_id", (o1, o2) -> o2);
            strategies.put("codeNode8_collect_product_info_str", (o1, o2) -> o2);
            strategies.put("httpNode4_files", (o1, o2) -> o2);
            strategies.put("LLMNode8_text", (o1, o2) -> o2);
            strategies.put("codeNode24_result", (o1, o2) -> o2);
            strategies.put("codeNode7_result", (o1, o2) -> o2);
            strategies.put("LLMNode10_text", (o1, o2) -> o2);
            strategies.put("LLMNode2_text", (o1, o2) -> o2);
            strategies.put("codeNode5_lessee_tags_str", (o1, o2) -> o2);
            strategies.put("LLMNode3_text", (o1, o2) -> o2);
            strategies.put("LLMNode16_text", (o1, o2) -> o2);
            strategies.put("collect_product_info", (o1, o2) -> o2);
            strategies.put("collect_product_info_str", (o1, o2) -> o2);
            strategies.put("httpNode6_body", (o1, o2) -> o2);
            strategies.put("huashu", (o1, o2) -> o2);
            strategies.put("LLMNode9_text", (o1, o2) -> o2);
            strategies.put("startNode1_customer_name", (o1, o2) -> o2);
            strategies.put("codeNode12_productScore", (o1, o2) -> o2);
            strategies.put("httpNode5_files", (o1, o2) -> o2);
            strategies.put("httpNode7_headers", (o1, o2) -> o2);
            strategies.put("codeNode23_result", (o1, o2) -> o2);
            strategies.put("codeNode2_special_scenarios", (o1, o2) -> o2);
            strategies.put("codeNode16_result", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode6_result", (o1, o2) -> o2);
            strategies.put("httpNode3_headers", (o1, o2) -> o2);
            strategies.put("answerNode3_answer", (o1, o2) -> o2);
            strategies.put("httpNode9_body", (o1, o2) -> o2);
            strategies.put("answerNode4_answer", (o1, o2) -> o2);
            strategies.put("answerNode2_answer", (o1, o2) -> o2);
            strategies.put("answerNode5_answer", (o1, o2) -> o2);
            strategies.put("codeNode14_customerDemand", (o1, o2) -> o2);
            strategies.put("answerNode1_answer", (o1, o2) -> o2);
            strategies.put("LLMNode19_text", (o1, o2) -> o2);
            strategies.put("LLMNode18_text", (o1, o2) -> o2);
            strategies.put("httpNode10_headers", (o1, o2) -> o2);
            strategies.put("codeNode11_total_score", (o1, o2) -> o2);
            strategies.put("httpNode8_body", (o1, o2) -> o2);
            strategies.put("codeNode1_character_design_str", (o1, o2) -> o2);
            strategies.put("httpNode10_files", (o1, o2) -> o2);
            strategies.put("startNode1_source", (o1, o2) -> o2);
            strategies.put("codeNode4_product_names_str", (o1, o2) -> o2);
            strategies.put("httpNode7_files", (o1, o2) -> o2);
            strategies.put("codeNode12_roundScore", (o1, o2) -> o2);
            strategies.put("questionClassifyNode1_class_name", (o1, o2) -> o2);
            strategies.put("image_product", (o1, o2) -> o2);
            strategies.put("stop_hosting", (o1, o2) -> o2);
            strategies.put("codeNode6_user_tags_str", (o1, o2) -> o2);
            strategies.put("httpNode4_headers", (o1, o2) -> o2);
            strategies.put("codeNode14_otherInfo", (o1, o2) -> o2);
            strategies.put("codeNode9_result", (o1, o2) -> o2);
            strategies.put("codeNode5_lessee_tags", (o1, o2) -> o2);
            strategies.put("codeNode25_result", (o1, o2) -> o2);
            strategies.put("codeNode4_filtered_product_data", (o1, o2) -> o2);
            strategies.put("codeNode12_totalScore", (o1, o2) -> o2);
            strategies.put("codeNode12_conclusion", (o1, o2) -> o2);
            strategies.put("httpNode8_headers", (o1, o2) -> o2);
            strategies.put("httpNode10_status_code", (o1, o2) -> o2);
            strategies.put("sceneId", (o1, o2) -> o2);
            strategies.put("httpNode8_files", (o1, o2) -> o2);
            strategies.put("httpNode5_headers", (o1, o2) -> o2);
            strategies.put("codeNode8_collect_product_info", (o1, o2) -> o2);
            strategies.put("LLMNode7_text", (o1, o2) -> o2);
            strategies.put("httpNode10_body", (o1, o2) -> o2);
            strategies.put("httpNode1_headers", (o1, o2) -> o2);
            strategies.put("codeNode21_result", (o1, o2) -> o2);
            strategies.put("httpNode7_body", (o1, o2) -> o2);
            strategies.put("knowledgeRetrievalNode8_result", (o1, o2) -> o2);
            strategies.put("httpNode4_body", (o1, o2) -> o2);
            strategies.put("httpNode2_files", (o1, o2) -> o2);
            strategies.put("LLMNode17_text", (o1, o2) -> o2);
            strategies.put("LLMNode4_text", (o1, o2) -> o2);
            strategies.put("codeNode19_id", (o1, o2) -> o2);
            strategies.put("LLMNode1_text", (o1, o2) -> o2);
            strategies.put("LLMNode14_text", (o1, o2) -> o2);
            strategies.put("LLMNode11_text", (o1, o2) -> o2);
            strategies.put("codeNode10_result", (o1, o2) -> o2);
            strategies.put("httpNode1_body", (o1, o2) -> o2);
            strategies.put("codeNode12_round", (o1, o2) -> o2);
            strategies.put("codeNode14_customerInfo", (o1, o2) -> o2);
            return strategies;
        }
        );
        // add nodes
        // —— HttpNode [17557641927460] ——
        HttpNode httpNode1 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-3362\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n  \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n  \\\"lesseeId\\\": \\\"${startNode1_lessee}\\\"\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode1_body")
                .build();
        stateGraph.addNode("httpNode1", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode1";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode1.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— HttpNode [17557656415320] ——
        HttpNode httpNode2 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-3513\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n  \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n  \\\"lesseeId\\\": ${startNode1_lessee}\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode2_body")
                .build();
        stateGraph.addNode("httpNode2", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode2";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode2.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [1755767729755] ——
        CodeExecutorNodeAction codeNode1 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
if not arg1:
   return {"character_design": {}, "character_design_str": "暂无角色设定"}

if isinstance(arg1, dict):
   response_data = arg1
else:
   try:
       response_data = json.loads(arg1)
   except json.JSONDecodeError:
       return {
           "character_design": {},
           "character_design_str": "输入的角色设定不是合法的 JSON",
       }

data = response_data.get("data", {}) if isinstance(response_data, dict) else {}

template = (
   "你是{name}，性别{sex}，使用的语言是{chatLang}。"
   "你的交流风格是{chatStyle}，并且精通{skill}。"
   "你现在正在作为{companyName}的销售人员，与客户沟通，该公司的主营产品包括{mainProducts}。"
   "目标客户群体主要是{customerGroup}。"
   "在对话中，你需要保持自然、亲切，同时展现专业度。"
   "回答要生动、有趣，并适当地融入{skill}文化元素，让客户感受到轻松和信任。"
   "在理解客户需求的基础上，自然地推荐合适的产品，强调这些产品如何符合客户的兴趣和风格。"
)

data_str = template.format(
   name=data.get("name", "未命名角色"),
   sex=data.get("sex", "未知"),
   skill=data.get("skill", "暂无技能"),
   companyName=data.get("companyName", "某公司"),
   mainProducts=data.get("mainProducts", "相关产品"),
   customerGroup=data.get("customerGroup", "客户群体"),
   chatStyle=data.get("chatStyle", "自然随和"),
   chatLang=data.get("chatLang", "英文"),
)

return {"character_design": data, "character_design_str": data_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode1_body"))
                .outputKey("codeNode1_output")
                .build();
        stateGraph.addNode("codeNode1", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode1.apply(state);
                    String key = "codeNode1_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode1_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1755767751197] ——
        CodeExecutorNodeAction codeNode2 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
    if not arg1:
        return {"special_scenarios": [], "special_scenarios_str": "暂无特殊场景"}

    try:
        # 修改点：先检查是否是字典，如果是则直接使用
        if isinstance(arg1, dict):
            response_data = arg1
        else:
            response_data = json.loads(arg1)

        data = response_data.get("data", [])
        cleaned_data = [dict(item) for item in data if isinstance(item, dict)]

        data_str = (
            json.dumps(cleaned_data, ensure_ascii=False, indent=2)
            if cleaned_data
            else "暂无特殊场景"
        )

        return {"special_scenarios": cleaned_data, "special_scenarios_str": data_str}
    except Exception as e:
        return {
            "special_scenarios": [],
            "special_scenarios_str": f"处理失败: {str(e)}"
        }
                        """)
                .config(codeExecutionConfig)
                .params(Map.of("arg1", "httpNode2_body"))
                .outputKey("codeNode2_output")
                .build();
        stateGraph.addNode("codeNode2", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode2.apply(state);
                    String key = "codeNode2_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode2_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— HttpNode [17557683471520] ——
        HttpNode httpNode3 = HttpNode.builder()
                .url(baseUrl + "/api/sale-rule/query/{{#1755760119759.lessee#}}")
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode3_body")
                .build();
        stateGraph.addNode("httpNode3", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode3";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode3.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [1755768706621] ——
        CodeExecutorNodeAction codeNode3 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
   if not arg1:
       return {"character_design": {}, "character_design_str": "暂无角色设定"}

   if isinstance(arg1, dict):
       response_data = arg1
   else:
       try:
           response_data = json.loads(arg1)
       except json.JSONDecodeError:
           return {
               "character_design": {},
               "character_design_str": "输入的角色设定不是合法的 JSON",
           }

   data = response_data.get("data", {}) if isinstance(response_data, dict) else {}

   template = (
       "你是{name}，性别{sex}，使用的语言是{chatLang}。"
       "你的交流风格是{chatStyle}，并且精通{skill}。"
       "你现在正在作为{companyName}的销售人员，与客户沟通，该公司的主营产品包括{mainProducts}。"
       "目标客户群体主要是{customerGroup}。"
       "在对话中，你需要保持自然、亲切，同时展现专业度。"
       "回答要生动、有趣，并适当地融入{skill}文化元素，让客户感受到轻松和信任。"
       "在理解客户需求的基础上，自然地推荐合适的产品，强调这些产品如何符合客户的兴趣和风格。"
   )

   data_str = template.format(
       name=data.get("name", "未命名角色"),
       sex=data.get("sex", "未知"),
       skill=data.get("skill", "暂无技能"),
       companyName=data.get("companyName", "某公司"),
       mainProducts=data.get("mainProducts", "相关产品"),
       customerGroup=data.get("customerGroup", "客户群体"),
       chatStyle=data.get("chatStyle", "自然随和"),
       chatLang=data.get("chatLang", "英文"),
   )

   return {"character_design": data, "character_design_str": data_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode3_body"))
                .outputKey("codeNode3_output")
                .build();
        stateGraph.addNode("codeNode3", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode3.apply(state);
                    String key = "codeNode3_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode3_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— HttpNode [17557763591460] ——
        HttpNode httpNode4 = HttpNode.builder()
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .queryParam("lesseeId", "${startNode1_lessee}")
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode4_body")
                .build();
        stateGraph.addNode("httpNode4", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode4";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode4.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [1755776428456] ——
        CodeExecutorNodeAction codeNode4 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
         if not arg1:
             return {
                 "filtered_product_data": [],
                 "product_names_list": [],
                 "product_names_str": "",
             }

         # 兼容 Java 传入 dict 或 str
         if isinstance(arg1, dict):
             response_data = arg1
         else:
             try:
                 response_data = json.loads(arg1)
             except json.JSONDecodeError:
                 return {
                     "filtered_product_data": [],
                     "product_names_list": [],
                     "product_names_str": "",
                 }

         data = response_data.get("data", [])
         filtered_output, product_names_list = [], []

         for product in data:
             product_name = product.get("productName", "")
             attributes = product.get("attributes", [])

             filtered_attrs = []
             for attr in attributes:
                 label = attr.get("label", "")
                 raw_desc = attr.get("description", "")
                 option_text = f"（可选的值有{raw_desc}）" if raw_desc else ""
                 filtered_attrs.append(
                     {
                         "label": label,
                         "description": f"现在客户想要【{product_name}】，请询问客户对于【{product_name}】的【{label}】需求{option_text}",
                         "score": attr.get("score", 10),
                         "value": attr.get("value", ""),
                     }
                 )

             if filtered_attrs:
                 filtered_output.append(
                     {
                         "productName": product_name,
                         "thresholdScore": product.get("thresholdScore", 20),
                         "totalScore": product.get("totalScore"),
                         "isQuotable": product.get("isQuotable", 0),
                         "attributes": filtered_attrs,
                     }
                 )
                 product_names_list.append(product_name)
     
         return {
             "filtered_product_data": filtered_output,
             "product_names_list": product_names_list,
             "product_names_str": json.dumps(product_names_list, ensure_ascii=False)
             if product_names_list
             else "",
         }
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode4_body"))
                .outputKey("codeNode4_output")
                .build();
        stateGraph.addNode("codeNode4", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode4.apply(state);
                    String key = "codeNode4_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode4_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— HttpNode [17558307127980] ——
        HttpNode httpNode5 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-4065\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n    \\\"apiKey\\\": ${env_app_key},\\n    \\\"lesseeId\\\": ${startNode1_lessee}\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode5_body")
                .build();
        stateGraph.addNode("httpNode5", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode5";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode5.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [17558307242790] ——
        CodeExecutorNodeAction codeNode5 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
   if not arg1:
       return {"lessee_tags": [], "lessee_tags_str": "[]"}

   if isinstance(arg1, dict):
       response_data = arg1
   else:
       try:
           response_data = json.loads(arg1)
       except json.JSONDecodeError:
           return {"lessee_tags": [], "lessee_tags_str": "[]"}

   data = response_data.get("data", [])
   lessee_tags = [
       {"tagId": item.get("tagId", ""), "tagName": item.get("tagName", "")}
       for item in data
       if isinstance(item, dict)
   ]

   lessee_tags_str = json.dumps(lessee_tags, ensure_ascii=False)

   return {"lessee_tags": lessee_tags, "lessee_tags_str": lessee_tags_str}
                       """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode5_body"))
                .outputKey("codeNode5_output")
                .build();
        stateGraph.addNode("codeNode5", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode5.apply(state);
                    String key = "codeNode5_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode5_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— BranchNode [1755849694052] ——
        stateGraph.addNode("branchNode1", AsyncNodeAction.node_async(state -> Map.of()));

// —— LlmNode [1755850441014] ——
        LlmNode LLMNode1 = LlmNode.builder()
                .systemPromptTemplate("你是一个智能助手，任务是判断用户消息是否触发特殊场景规则。\n\n输入：\n- 特殊场景：{codeNode2_special_scenarios_str}\n- 商家在售商品：{codeNode4_product_names_str}\n\n规则：\n1. 如果用户消息触发了特殊场景规则，返回完整场景信息，数组形式（多个场景同时触发时全部返回）。\n2. 如果未触发，返回空数组 []。\n3. 判断触发原因要基于：\n   - 消息内容匹配场景关键词或规则  \n   - 消息内容涉及在售商品  \n4. **禁止输出用户消息内容或其他文字**，只输出 JSON。  ")
                .params(Map.of("codeNode2_special_scenarios_str", "null", "codeNode4_product_names_str", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode1_text")
                .build();
        stateGraph.addNode("LLMNode1", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode1.apply(state);
                    String key = "LLMNode1_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— HttpNode [1755853472970] ——
        HttpNode httpNode6 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-109\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n  \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n  \\\"sceneId\\\": ${conversation_sceneId},\\n  \\\"lesseeId\\\": ${startNode1_lessee},\\n  \\\"imUserId\\\": ${sys_user_id},\\n  \\\"msgId\\\": ${startNode1_message_id},\\n  \\\"conversationId\\\": \\\"${startNode1_server_conversation_id}\\\"\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode6_body")
                .build();
        stateGraph.addNode("httpNode6", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode6";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode6.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— LlmNode [1755854546432] ——
        LlmNode LLMNode2 = LlmNode.builder()
                .systemPromptTemplate("请根据以下信息生成客户简要画像数组，输出格式严格为一个数组，数组内包含一个对象，对象字段如下：\n\n{\n  \"customerInfo\": \"简要总结客户背景和特征\",\n  \"customerDemand\": \"简要总结客户商品需求\",\n  \"otherInfo\": \"简要总结客户问题、关注点或其他附加信息\"\n}\n\n输入信息：\n客户之前的总结分析：{codeNode6_customer_analysis_str}\n客户需求商品：{conversation_collect_product_info_str}")
                .params(Map.of("conversation_collect_product_info_str", "null", "codeNode6_customer_analysis_str", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode2_text")
                .build();
        stateGraph.addNode("LLMNode2", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode2.apply(state);
                    String key = "LLMNode2_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— HttpNode [17558556503520] ——
        HttpNode httpNode7 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-8343\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n    \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n    \\\"lesseeId\\\": ${startNode1_lessee},\\n    \\\"imUserId\\\": ${sys_user_id}\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode7_body")
                .build();
        stateGraph.addNode("httpNode7", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode7";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode7.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— HttpNode [1755856286673] ——
        HttpNode httpNode8 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-1500\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n  \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n  \\\"lesseeId\\\": ${startNode1_lessee},\\n  \\\"imUserId\\\": ${sys_user_id},\\n  \\\"customerInfo\\\": ${codeNode14_customerInfo},\\n  \\\"customerDemand\\\": ${codeNode14_customerDemand},\\n  \\\"otherInfo\\\": ${codeNode14_otherInfo}\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode8_body")
                .build();
        stateGraph.addNode("httpNode8", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode8";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode8.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— LlmNode [1755856306126] ——
        LlmNode LLMNode3 = LlmNode.builder()
                .systemPromptTemplate("请根据以下信息为客户打标签（只能从可选标签列表中选，禁止生成新标签）：\n客户信息：\n客户需求商品：{conversation_collect_product_info_str}\n可选标签列表：{codeNode5_lessee_tags_str}\n客户已有标签：{codeNode6_user_tags_str}\n输出格式：只列出新增标签，不重复已有标签。")
                .params(Map.of("conversation_collect_product_info_str", "null", "codeNode5_lessee_tags_str", "null", "codeNode6_user_tags_str", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode3_text")
                .build();
        stateGraph.addNode("LLMNode3", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode3.apply(state);
                    String key = "LLMNode3_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— HttpNode [1755857078513] ——
        HttpNode httpNode9 = HttpNode.builder()
                .method(HttpMethod.POST)
                .url(baseUrl + "/lessee/inner/roleSetting/get")
                .body(HttpNode.HttpRequestNodeBody.fromJson("{\"data\":[{\"id\":\"key-value-9063\",\"key\":\"\",\"type\":\"text\",\"value\":\"{\\n    \\\"apiKey\\\": \\\"${env_app_key}\\\",\\n    \\\"imUserId\\\": ${sys_user_id},\\n    \\\"tagIds\\\": ${codeNode7_result}\\n}\"}],\"type\":\"json\"}"))
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode9_body")
                .build();
        stateGraph.addNode("httpNode9", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode9";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode9.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [1755916796748] ——
        CodeExecutorNodeAction codeNode6 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
 if isinstance(arg1, dict):
     data = arg1
 else:
     try:
         data = json.loads(arg1)
     except json.JSONDecodeError:
         data = {}

 user_data = data.get("data", {})

 customer_fields = ["customerInfo", "customerDemand", "otherInfo"]
 customer_data = {k: user_data[k] for k in customer_fields if k in user_data}

 user_tags_str = json.dumps(user_data.get("tags", []), ensure_ascii=False)

 return {
     "custom_info": user_data,
     "customer_analysis_str": json.dumps(customer_data, ensure_ascii=False),
     "user_tags_str": user_tags_str,
 }
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode7_body"))
                .outputKey("codeNode6_output")
                .build();
        stateGraph.addNode("codeNode6", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode6.apply(state);
                    String key = "codeNode6_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode6_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1755942129724] ——
        CodeExecutorNodeAction codeNode7 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
                        def main(arg1: dict) -> dict:
                            return {"result": json.dumps(arg1)}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode3_structured_output"))
                .outputKey("codeNode7_output")
                .build();
        stateGraph.addNode("codeNode7", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode7.apply(state);
                    String key = "codeNode7_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode7_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1755945926794] ——
        CodeExecutorNodeAction codeNode8 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import copy
import json
def main(arg1: list, arg2: list[dict], arg3: list[dict]):
 product_map = {
     item["product"]: item
     for item in arg2
     if isinstance(item, dict) and "product" in item
 }

 updated_arg3 = copy.deepcopy(arg3) if arg3 else []

 for i, item in enumerate(updated_arg3):
     product_name = item.get("product")
     ref_product = product_map.get(product_name)
     if not ref_product:
         continue
     ref_attrs_map = {a["label"]: a for a in ref_product.get("attributes", [])}
     new_attrs = []
     for attr in item.get("attributes", []):
         label = attr.get("label")
         if label not in ref_attrs_map:
             continue
         ref_attr = ref_attrs_map[label]
         merged_attr = attr.copy()

         for key in ["id", "label", "description", "score"]:
             merged_attr[key] = ref_attr.get(key, merged_attr.get(key))

         new_attrs.append(merged_attr)
     updated_arg3[i]["attributes"] = new_attrs

 if arg1:
     collected_products = {item.get("product") for item in updated_arg3}
     for product_name in arg1:
         product_name = product_name.strip()
         if product_name in collected_products:
             continue
         ref_product = product_map.get(product_name)
         if not ref_product:
             continue
         new_attrs = [attr.copy() for attr in ref_product.get("attributes", [])]
         updated_arg3.append({"product": product_name, "attributes": new_attrs})

 return {
     "collect_product_info": updated_arg3,
     "collect_product_info_str": json.dumps(updated_arg3, ensure_ascii=False),
 }
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode5_structured_output", "arg2", "codeNode4_filtered_product_data", "arg3", "conversation_collect_product_info"))
                .outputKey("codeNode8_output")
                .build();
        stateGraph.addNode("codeNode8", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode8.apply(state);
                    String key = "codeNode8_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode8_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— LlmNode [1755947932458] ——
        LlmNode LLMNode4 = LlmNode.builder()
                .systemPromptTemplate("这是客户可能需要的商品信息：\n{conversation_collect_product_info_str}\n这是用户可能上传的图片信息：\n{conversation_image_analysis}\n\n规则：\n1. 只能输出 JSON，不允许输出任何多余文字、解释、总结或问题。\n2. 如果商品信息为空，请输出空数组：\n   {\"product_information\": []}\n3. 从上下文中提取商品属性填入对应 value：\n   - 找到对应值则填入 value\n   - 未找到则 value 为 \"\"\n4. 输出 JSON 必须完全符合 Schema，禁止任何额外字段。\n5. 不允许自然语言回答，不允许中文说明或提示。")
                .params(Map.of("conversation_collect_product_info_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode4_text")
                .build();
        stateGraph.addNode("LLMNode4", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode4.apply(state);
                    String key = "LLMNode4_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— AssignerNode [1755948713597] ——
        AssignerNode assignerNode1 = AssignerNode.builder()
                .addItem("conversation_collect_product_info_str", "codeNode8_collect_product_info_str", AssignerNode.WriteMode.OVER_WRITE)
                .addItem("conversation_collect_product_info", "codeNode8_collect_product_info", AssignerNode.WriteMode.OVER_WRITE)
                .build();
        stateGraph.addNode("assignerNode1", AsyncNodeAction.node_async(assignerNode1));

// —— LlmNode [1755949477160] ——
        LlmNode LLMNode5 = LlmNode.builder()
                .systemPromptTemplate("你是一个智能助手，任务是判断用户是否需要购买在售商品，并输出严格符合 JSON schema 的结果。\n\n输入：\n- 在售商品列表：{codeNode4_product_names_str}\n- 已收集的需求商品：{conversation_collect_product_info_str}\n- 图片文本描述：{conversation_image_analysis}\n规则：\n1. 优先使用图片文本描述匹配在售商品（完全匹配或包含关键词）。\n2. 如果图片匹配不到，再使用已收集需求商品匹配在售商品。\n3. **不要输出任何额外文字**，只输出 JSON。")
                .params(Map.of("conversation_collect_product_info_str", "null", "codeNode4_product_names_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode5_text")
                .build();
        stateGraph.addNode("LLMNode5", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode5.apply(state);
                    String key = "LLMNode5_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— CodeNode [17560179385050] ——
        CodeExecutorNodeAction codeNode9 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
 if not arg1:
     return {"result": ""}
 return {
     "result": json.dumps(arg1, ensure_ascii=False),
 }

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode4_structured_output"))
                .outputKey("codeNode9_output")
                .build();
        stateGraph.addNode("codeNode9", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode9.apply(state);
                    String key = "codeNode9_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode9_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— LlmNode [1756018471542] ——
        LlmNode LLMNode6 = LlmNode.builder()
                .systemPromptTemplate("角色设定：{codeNode1_character_design_str}\n你是一个真人！！！\n\n规则：\n严格遵守商家规则和当前销售阶段。\n按销售思维引导客户。\nFAQ 优先：若客户问题匹配 FAQ，参考FAQ回答思路。\n若用户提到商品具体属性值，不要再重复追问\n\n回答直接原则\n1、保持简洁，回复字数不超过40字！！！！\n2、若商品 value 为空，自然询问客户补充。\n3、第一句话就要直接回答问题核心\n4、用英文回复\n5、必须分句回复，将文本按句末标点（. ? !）分割成独立句子，在后面加###\n6、推送链接时必须从资源库{codeNode16_result}中推送3-5个，禁止编造链接，必须以https开头的格式输出\n\n禁止原则\n1、禁止回复字数超过40个字\n2、禁止一句话不说完整\n3、禁止连续提问\n4、禁止同样、相近意思的话重复说\n5、禁止分点输出\n6、禁止编造任何信息、链接\n\n输入信息：\n商家规则：{codeNode3_general_rules_str}\n销售阶段：{codeNode18_result}\n销售思维：{codeNode10_result}\n客户意向商品：{conversation_collect_product_info_str}\n资源库：{codeNode16_result}\nFAQ：{codeNode17_result}\n用户可能上传图片信息：{conversation_image_analysis}")
                .params(Map.of("codeNode3_general_rules_str", "null", "conversation_collect_product_info_str", "null", "codeNode1_character_design_str", "null", "codeNode16_result", "null", "codeNode18_result", "null", "codeNode17_result", "null", "codeNode10_result", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode6_text")
                .build();
        stateGraph.addNode("LLMNode6", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode6.apply(state);
                    String key = "LLMNode6_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— LlmNode [1756019111848] ——
        LlmNode LLMNode7 = LlmNode.builder()
                .systemPromptTemplate("你是一个情商极高的销售")
                .chatClient(chatClient)
                .outputKey("LLMNode7_text")
                .build();
        stateGraph.addNode("LLMNode7", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode7.apply(state);
                    String key = "LLMNode7_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— CodeNode [1756019266673] ——
        CodeExecutorNodeAction codeNode10 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import re
import json
def main(arg1) -> dict:
   if not arg1:
       return {"result": ""}

   tags = ["summary", "think"]
   for tag in tags:
       matches = re.findall(
           rf"<{tag}>(.*?)</{tag}>",
           arg1,
           re.DOTALL | re.IGNORECASE,
       )
       for content in matches:
           content = content.strip()
           if content:
               return {"result": content}
   return {"result": arg1}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode7_text"))
                .outputKey("codeNode10_output")
                .build();
        stateGraph.addNode("codeNode10", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode10.apply(state);
                    String key = "codeNode10_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode10_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— AnswerNode [1756019370286] ——
        AnswerNode answerNode1 = AnswerNode.builder()
                .answer("<think>{codeNode10_result}</think>\n{codeNode13_result}")
                .outputKey("answerNode1_answer")
                .build();
        stateGraph.addNode("answerNode1", AsyncNodeAction.node_async(answerNode1));

        stateGraph.addEdge("answerNode1", END);
// —— CodeNode [1756020347663] ——
        CodeExecutorNodeAction codeNode11 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
def main(
    arg1: list[dict], arg2: float, arg3: float, arg4: float, arg5: float, arg6: float
) -> dict:
    result = []
    bonus = arg5 if arg3 == arg4 else 0
    global_score = 0
    hit_count = 0

    for product in arg1:
        product_score = 0
        filtered_attrs = []

        for attr in product.get("attributes", []):
            if attr.get("value"):
                product_score += attr.get("score", 0)
                filtered_attrs.append(
                    {k: v for k, v in attr.items() if k not in ("score",)}
                )

        global_score += product_score
        if filtered_attrs:
            hit_count += 1
            result.append(
                {
                    "productName": product.get("productName"),
                    "attributes": filtered_attrs,
                }
            )

    total_score = global_score + bonus + hit_count * arg6
    return {"result": result if total_score >= arg2 else [], "total_score": total_score}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "conversation_collect_product_info", "arg2", "codeNode12_totalScore", "arg3", "sys_dialogue_count", "arg4", "codeNode12_round", "arg5", "codeNode12_roundScore", "arg6", "codeNode12_productScore"))
                .outputKey("codeNode11_output")
                .build();
        stateGraph.addNode("codeNode11", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode11.apply(state);
                    String key = "codeNode11_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode11_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— BranchNode [1756020912920] ——
        stateGraph.addNode("branchNode2", AsyncNodeAction.node_async(state -> Map.of()));

// —— LlmNode [1756021890832] ——
        LlmNode LLMNode8 = LlmNode.builder()
                .systemPromptTemplate("请生成一条正式且温和的结束语：\n结束语模板：{codeNode12_conclusion}\n\n要求：\n1. 如果模板有值，用意思相近的英文表达；\n2. 如果模板为空，自由发挥，用英文表达。\n3. 内容意思为“我们正在处理您的请求，请耐心等待”，用词简洁自然，避免与常见表达完全雷同。")
                .params(Map.of("codeNode12_conclusion", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode8_text")
                .build();
        stateGraph.addNode("LLMNode8", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode8.apply(state);
                    String key = "LLMNode8_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— AnswerNode [1756021965125] ——
        AnswerNode answerNode2 = AnswerNode.builder()
                .answer("{LLMNode8_text}")
                .outputKey("answerNode2_answer")
                .build();
        stateGraph.addNode("answerNode2", AsyncNodeAction.node_async(answerNode2));

        stateGraph.addEdge("answerNode2", END);
// —— LlmNode [1756028965021] ——
        LlmNode LLMNode9 = LlmNode.builder()
                .systemPromptTemplate("你是一个智能助手，任务是根据用户上传图片生成结构化 JSON 描述。\n\n输入：\n- 用户上传图片内容（文本描述）  \n- 在售商品类别列表：{codeNode4_product_names_list}\n\n规则：\n1. 先详细描述图片内容，写清楚场景、物品、颜色、动作等关键信息。  \n2. 判断图片内容是否与在售商品类别有关：\n   - 如果相关：输出图片描述 + 对应商品类别  \n   - 如果无关：输出图片描述，并将商品类别设为 \"无相关商品种类\"  \n3. **禁止回答用户问题或生成额外文字，只输出 JSON**  ")
                .params(Map.of("codeNode4_product_names_list", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode9_text")
                .build();
        stateGraph.addNode("LLMNode9", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode9.apply(state);
                    String key = "LLMNode9_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— LlmNode [1756029346700] ——
        LlmNode LLMNode10 = LlmNode.builder()
                .systemPromptTemplate("根据客户图片{conversation_image_analysis}、对话及客户意向商品信息{conversation_collect_product_info_str}生成知识库检索语句（禁止回答问题）。  \n规则：若用户需要购买商品输出检索语句，否则输出“无”。  \n可参考的输出字段：名称, 适用人群性别, 适用人群年龄, 标签, 销售价格, 图片描述。  \n优先级：意向商品信息>用户上下文。模糊时可用关键词、类别或标签匹配。  \n每个字段一行，字段值需要英文")
                .params(Map.of("conversation_collect_product_info_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode10_text")
                .build();
        stateGraph.addNode("LLMNode10", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode10.apply(state);
                    String key = "LLMNode10_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— KnowledgeRetrievalNode [1756029554923] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode1 = KnowledgeRetrievalNode.builder()
                .inputKey("LLMNode10_text")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(1.0)
                .outputKey("knowledgeRetrievalNode1_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode1", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode1_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode1.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— KnowledgeRetrievalNode [1756029815656] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode2 = KnowledgeRetrievalNode.builder()
                .inputKey("LLMNode11_text")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode2_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode2", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode2_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode2.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— LlmNode [1756029898843] ——
        LlmNode LLMNode11 = LlmNode.builder()
                .systemPromptTemplate("根据上传图片{conversation_image_analysis}和客户意向商品信息{conversation_collect_product_info_str}，判断用户意图（售前、售后、使用指导、优惠、技术支持等），提取关键实体（型号、品牌、购买历史、关注点等），生成英文关键词或短语的 FAQ 查询语句，用于向量搜索。  \n禁止回答用户问题。\n输出纯英文文本，仅查询语句。若无法生成，输出“无”。")
                .params(Map.of("conversation_collect_product_info_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode11_text")
                .build();
        stateGraph.addNode("LLMNode11", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode11.apply(state);
                    String key = "LLMNode11_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— LlmNode [1756030383240] ——
        LlmNode LLMNode12 = LlmNode.builder()
                .systemPromptTemplate("根据上传图片{conversation_image_analysis}和客户意向商品{conversation_collect_product_info_str}生成知识库检索关键词（禁止回答问题）。  \n规则：提取核心主题和购买需求，输出具体商品名称、类别或标签，避免模糊描述。  \n如果当前信息没有意向商品，则生成对应商品种类的查询语句。\n优先级：意向商品 > 用户上下文。  \n若无法提取关键词或信息为空，输出“无”。  ")
                .params(Map.of("conversation_collect_product_info_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode12_text")
                .build();
        stateGraph.addNode("LLMNode12", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode12.apply(state);
                    String key = "LLMNode12_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— KnowledgeRetrievalNode [1756030505337] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode3 = KnowledgeRetrievalNode.builder()
                .inputKey("LLMNode12_text")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode3_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode3", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode3_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode3.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— LlmNode [1756087090945] ——
        LlmNode LLMNode13 = LlmNode.builder()
                .systemPromptTemplate("根据上传图片{conversation_image_analysis}和客户意向商品{conversation_collect_product_info_str}，判断销售阶段（陌生、兴趣、信任、意向、订单、成交、复购），提炼客户关注的核心问题或词语，并生成向量检索字段。 \n禁止回答客户问题。\n输出格式：阶段: <阶段> | 要点: <沟通策略> | 客户提问: <客户关注点>")
                .params(Map.of("conversation_collect_product_info_str", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode13_text")
                .build();
        stateGraph.addNode("LLMNode13", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode13.apply(state);
                    String key = "LLMNode13_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— KnowledgeRetrievalNode [1756087097420] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode4 = KnowledgeRetrievalNode.builder()
                .inputKey("LLMNode13_text")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode4_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode4", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode4_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode4.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— HttpNode [1756089028563] ——
        HttpNode httpNode10 = HttpNode.builder()
                .url(baseUrl + "/api/mind/query/{{#1755760119759.lessee#}}")
                .retryConfig(new HttpNode.RetryConfig(3, 100, true))
                .outputKey("httpNode10_body")
                .build();
        stateGraph.addNode("httpNode10", AsyncNodeAction.node_async(state -> {
                    String varName = "httpNode10";
                    String key = varName + "_body";
                    Map<String, Object> result = httpNode10.apply(state);
                    Object object = result.get(key);
                    if (!(object instanceof Map<?, ?> map)) {
                        return Map.of();
                    }
                    return Map.of(varName + "_headers", map.get("headers"), key, map.get("body"),
                            varName + "_status_code", map.get("status"));
                }
        ));

// —— CodeNode [1756089146690] ——
        CodeExecutorNodeAction codeNode12 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json
def main(arg1) -> dict:
     if isinstance(arg1, dict):
         data = arg1.get("data", {})
     else:
         try:
             data = json.loads(arg1).get("data", {})
         except (json.JSONDecodeError, TypeError, AttributeError):
             data = {}
 
     result = {
         "totalScore": data.get("totalScore", 50),
         "round": data.get("round", 5),
         "roundScore": data.get("roundScore", 10),
         "productScore": data.get("productScore", 10),
         "conclusion": data.get("endStatement")
         or "I'm carefully handling it now. It may take just a moment, and I truly appreciate your patience.",
     }
 
     return result
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "httpNode10_body"))
                .outputKey("codeNode12_output")
                .build();
        stateGraph.addNode("codeNode12", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode12.apply(state);
                    String key = "codeNode12_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode12_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— AssignerNode [17560916613730] ——
        AssignerNode assignerNode2 = AssignerNode.builder()
                .addItem("conversation_sceneId", "codeNode19_id", AssignerNode.WriteMode.OVER_WRITE)
                .addItem("conversation_stop_hosting", "codeNode19_stopHosting", AssignerNode.WriteMode.OVER_WRITE)
                .build();
        stateGraph.addNode("assignerNode2", AsyncNodeAction.node_async(assignerNode2));

// —— AssignerNode [1756104138927] ——
        AssignerNode assignerNode3 = AssignerNode.builder()
                .addItem("conversation_image_analysis", "LLMNode9_structured_output", AssignerNode.WriteMode.OVER_WRITE)
                .addItem("conversation_image_product", "LLMNode9_structured_output", AssignerNode.WriteMode.OVER_WRITE)
                .build();
        stateGraph.addNode("assignerNode3", AsyncNodeAction.node_async(assignerNode3));

// —— CodeNode [1756112512454] ——
        CodeExecutorNodeAction codeNode13 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import re
import json
def main(arg1):
  if not arg1:
      return {"result": ""}
  matches = re.sub(r"<think>[\\s\\S]*?</think>", "", arg1, flags=re.IGNORECASE).strip()
  return {"result": matches}
                      """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode6_text"))
                .outputKey("codeNode13_output")
                .build();
        stateGraph.addNode("codeNode13", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode13.apply(state);
                    String key = "codeNode13_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode13_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1756114974542] ——
        CodeExecutorNodeAction codeNode14 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json
def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, dict):
         return {
             "customerInfo": "",
             "customerDemand": "",
             "otherInfo": ""
         }
     return {
         "customerInfo": arg1.get("customerInfo", ""),
         "customerDemand": arg1.get("customerDemand", ""),
         "otherInfo": arg1.get("otherInfo", "")
     }

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode2_structured_output"))
                .outputKey("codeNode14_output")
                .build();
        stateGraph.addNode("codeNode14", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode14.apply(state);
                    String key = "codeNode14_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode14_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— BranchNode [1756178976150] ——
        stateGraph.addNode("branchNode3", AsyncNodeAction.node_async(state -> Map.of()));

// —— CodeNode [1756210098116] ——
        CodeExecutorNodeAction codeNode15 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         content = item.get("content", "")
         score = item.get("metadata", {}).get("score", 0)
 
         def extract_field(field_name):
             for line in content.split("\\n"):
                 if line.startswith(field_name + ":"):
                     return line.split(":", 1)[1].strip()
             return ""
 
         keywords = extract_field("关键词")
         name = extract_field("名称")
         gender = extract_field("适用人群性别")
         age = extract_field("适用人群年龄")
         supplier = extract_field("供应商（厂商）")
         price = extract_field("销售价格")
         ref_price = extract_field("参考原价")
         image_url = extract_field("图片")
 
         item_str = (
             f"{idx}. 关键词: {keywords}; 商品名称: {name}; 适用人群性别: {gender}; 适用人群年龄: {age}; "
             f"供应商（厂商）: {supplier}; 销售价格: {price}; 参考原价: {ref_price}; 图片链接: {image_url}; 相似度: {score:.3f}"
         )
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode1_result"))
                .outputKey("codeNode15_output")
                .build();
        stateGraph.addNode("codeNode15", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode15.apply(state);
                    String key = "codeNode15_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode15_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [17562101241090] ——
        CodeExecutorNodeAction codeNode16 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import re
import json
def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
 
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         content = item.get("content", "")
         score = item.get("metadata", {}).get("score", 0)
 
         def extract_field(field_name):
             # 用正则更稳妥，匹配 “字段名: 内容 |” 或 “字段名: 内容” 到结尾
             match = re.search(rf"{field_name}\\s*:\\s*([^|]+)", content)
             if match:
                 return match.group(1).strip()
             return ""
 
         keywords = extract_field("关键字")
         resource_path = extract_field("资源路径")
 
         item_str = f"{idx}. 内容关键词: {keywords}; 资源链接: {resource_path}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
     return {"result": result_str}

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode3_result"))
                .outputKey("codeNode16_output")
                .build();
        stateGraph.addNode("codeNode16", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode16.apply(state);
                    String key = "codeNode16_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode16_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [17562101451170] ——
        CodeExecutorNodeAction codeNode17 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json
def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         content = item.get("content", "").strip()
         score = item.get("metadata", {}).get("score", 0)
 
         item_str = f"{idx}. 内容: {content}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode2_result"))
                .outputKey("codeNode17_output")
                .build();
        stateGraph.addNode("codeNode17", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode17.apply(state);
                    String key = "codeNode17_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode17_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [17562101662250] ——
        CodeExecutorNodeAction codeNode18 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json
def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         if not isinstance(item, dict):
             continue
         content = item.get("content", "").strip()
         score = item.get("metadata", {}).get("score", 0)
 
         item_str = f"{idx}. 内容: {content}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode4_result"))
                .outputKey("codeNode18_output")
                .build();
        stateGraph.addNode("codeNode18", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode18.apply(state);
                    String key = "codeNode18_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode18_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1756450218887] ——
        CodeExecutorNodeAction codeNode19 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json
def main(arg1) -> dict:
         if not arg1 or not isinstance(arg1, list):
             return {"id": "", "stopHosting": "0"}
     
         first_item = arg1[0]
         if not isinstance(first_item, dict):
             return {"id": "", "stopHosting": "0"}
     
         return {
             "id": str(first_item.get("id", "")),
             "stopHosting": first_item.get("stopHosting", "0"),
         }
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode1_structured_output"))
                .outputKey("codeNode19_output")
                .build();
        stateGraph.addNode("codeNode19", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode19.apply(state);
                    String key = "codeNode19_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode19_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— AssignerNode [1756451387126] ——
        AssignerNode assignerNode4 = AssignerNode.builder()
                .addItem("conversation_sceneId", null, AssignerNode.WriteMode.OVER_WRITE)
                .build();
        stateGraph.addNode("assignerNode4", AsyncNodeAction.node_async(assignerNode4));

// —— BranchNode [1756454234375] ——
        stateGraph.addNode("branchNode4", AsyncNodeAction.node_async(state -> Map.of()));

// —— LlmNode [1756870955241] ——
        LlmNode LLMNode14 = LlmNode.builder()
                .systemPromptTemplate("根据用户当前问题和可能需求的商品信息，输出json格式\n\n客户需要的商品信息：{conversation_collect_product_info_str}\n客户可能上传的图片描述：{conversation_image_analysis}\n可报价的商品：{codeNode26_quotableProductNames}\n\n禁止回答用户问题")
                .params(Map.of("conversation_collect_product_info_str", "null", "codeNode26_quotableProductNames", "null", "conversation_image_analysis", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode14_text")
                .build();
        stateGraph.addNode("LLMNode14", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode14.apply(state);
                    String key = "LLMNode14_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— KnowledgeRetrievalNode [1756871219944] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode5 = KnowledgeRetrievalNode.builder()
                .inputKey("sys_query")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode5_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode5", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode5_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode5.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— KnowledgeRetrievalNode [1756871225455] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode6 = KnowledgeRetrievalNode.builder()
                .inputKey("codeNode25_result")
                .topK(6)
                .enableRanker(false)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode6_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode6", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode6_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode6.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— CodeNode [1756871294869] ——
        CodeExecutorNodeAction codeNode20 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         if not isinstance(item, dict):
             continue
         content = item.get("content", "").strip()
         score = item.get("metadata", {}).get("score", 0)
 
         item_str = f"{idx}. 内容: {content}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode5_result"))
                .outputKey("codeNode20_output")
                .build();
        stateGraph.addNode("codeNode20", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode20.apply(state);
                    String key = "codeNode20_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode20_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [1756871343886] ——
        CodeExecutorNodeAction codeNode21 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         if not isinstance(item, dict):
             continue
         content = item.get("content", "")
         score = item.get("metadata", {}).get("score", 0)
 
         def extract_field(field_name):
             for line in content.split("\\n"):
                 if line.startswith(field_name + ":"):
                     return line.split(":", 1)[1].strip()
             return ""
 
         keywords = extract_field("关键词")
         name = extract_field("名称")
         gender = extract_field("适用人群性别")
         age = extract_field("适用人群年龄")
         supplier = extract_field("供应商（厂商）")
         price = extract_field("销售价格")
         ref_price = extract_field("参考原价")
         image_url = extract_field("图片")
 
         item_str = (
             f"{idx}. 关键词: {keywords}; 商品名称: {name}; 适用人群性别: {gender}; 适用人群年龄: {age}; "
             f"供应商（厂商）: {supplier}; 销售价格: {price}; 参考原价: {ref_price}; 图片链接: {image_url}; 相似度: {score:.3f}"
         )
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode6_result"))
                .outputKey("codeNode21_output")
                .build();
        stateGraph.addNode("codeNode21", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode21.apply(state);
                    String key = "codeNode21_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode21_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— LlmNode [1756871378233] ——
        LlmNode LLMNode15 = LlmNode.builder()
                .systemPromptTemplate("请你参考商品检索价格\n\n给客户报一个范围价格\n\n")
                .chatClient(chatClient)
                .outputKey("LLMNode15_text")
                .build();
        stateGraph.addNode("LLMNode15", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode15.apply(state);
                    String key = "LLMNode15_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— KnowledgeRetrievalNode [1756884444744] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode7 = KnowledgeRetrievalNode.builder()
                .inputKey("sys_query")
                .topK(3)
                .enableRanker(false)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(1.0)
                .outputKey("knowledgeRetrievalNode7_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode7", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode7_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode7.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— CodeNode [17568845128680] ——
        CodeExecutorNodeAction codeNode22 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         if not isinstance(item, dict):
             continue
         content = item.get("content", "")
         score = item.get("metadata", {}).get("score", 0)
 
         def extract_field(field_name):
             for part in content.split(";"):
                 if field_name in part:
                     return part.split(":", 1)[1].strip().strip('"')
             return ""
 
         resource_content = extract_field("resource_content")
         resource_img = extract_field("resource_img")
 
         item_str = f"{idx}. 内容关键词: {resource_content}; 图片链接: {resource_img}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode7_result"))
                .outputKey("codeNode22_output")
                .build();
        stateGraph.addNode("codeNode22", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode22.apply(state);
                    String key = "codeNode22_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode22_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— AssignerNode [1756884979577] ——
        AssignerNode assignerNode5 = AssignerNode.builder()
                .addItem("conversation_huashu", "codeNode22_result", AssignerNode.WriteMode.OVER_WRITE)
                .build();
        stateGraph.addNode("assignerNode5", AsyncNodeAction.node_async(assignerNode5));

// —— KnowledgeRetrievalNode [17573828773850] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode8 = KnowledgeRetrievalNode.builder()
                .inputKey("sys_query")
                .topK(4)
                .enableRanker(true)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode8_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode8", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode8_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode8.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— KnowledgeRetrievalNode [17573828917380] ——
        KnowledgeRetrievalNode knowledgeRetrievalNode9 = KnowledgeRetrievalNode.builder()
                .inputKey("sys_query")
                .topK(3)
                .enableRanker(false)
                .retrievalMode("multiple")
                .embeddingModelName("text-embedding-3-small")
                .embeddingProviderName("langgenius/openai/openai")
                .vectorWeight(0.7)
                .outputKey("knowledgeRetrievalNode9_result")
                .vectorStore(vectorStore)
                .isKeyFirst(false).build();
        stateGraph.addNode("knowledgeRetrievalNode9", AsyncNodeAction.node_async((state) -> {
                    String key = "knowledgeRetrievalNode9_result";
                    // 将结果转换为Dify工作流中需要的变量
                    Map<String, Object> result = knowledgeRetrievalNode9.apply(state);
                    Object object = result.get(key);
                    if (object instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Document) {
                        // 返回值为Array[Object]（用List<Map>）
                        List<Document> documentList = (List<Document>) list;
                        List<Map<String, Object>> mapList = documentList.stream().map(document ->
                                        Map.of("content", document.getFormattedContent(), "title", document.getId(), "url", "", "icon", "", "metadata", document.getMetadata()))
                                .toList();
                        return Map.of(key, mapList);
                    } else {
                        return Map.of(key, List.of(Map.of("content", object.toString(), "title", "unknown", "url", "unknown", "icon", "unknown", "metadata", object)));
                    }
                }
        ));

// —— CodeNode [17573829291670] ——
        CodeExecutorNodeAction codeNode23 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
     if not arg1 or not isinstance(arg1, list):
         return {"result": ""}
     result_list = []
     for idx, item in enumerate(arg1, start=1):
         if not isinstance(item, dict):
             continue
         content = item.get("content", "").strip()
         score = item.get("metadata", {}).get("score", 0)
 
         item_str = f"{idx}. 内容: {content}; 相似度: {score:.3f}"
         result_list.append(item_str)
 
     result_str = "\\n".join(result_list)
 
     return {"result": result_str}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode8_result"))
                .outputKey("codeNode23_output")
                .build();
        stateGraph.addNode("codeNode23", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode23.apply(state);
                    String key = "codeNode23_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode23_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— CodeNode [17573829335420] ——
        CodeExecutorNodeAction codeNode24 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
import json

def main(arg1) -> dict:
    if not arg1 or not isinstance(arg1, list):
        return {"result": json.dumps([])}

    result_list = []
    for idx, item in enumerate(arg1, start=1):
        if not isinstance(item, dict):
            continue
        content = item.get("content", "").strip()
        score = item.get("metadata", {}).get("score", 0)
        result_list.append({
            "index": idx,
            "content": content,
            "score": round(score, 3)
        })

    return {"result": json.dumps(result_list, ensure_ascii=False, indent=2)}
                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "knowledgeRetrievalNode9_result"))
                .outputKey("codeNode24_output")
                .build();
        stateGraph.addNode("codeNode24", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode24.apply(state);
                    String key = "codeNode24_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode24_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— LlmNode [1757382975020] ——
        LlmNode LLMNode16 = LlmNode.builder()
                .systemPromptTemplate("你是一个专业销售。\n这是知识库检索到的查询：销售话术和共情话术，请你根据用户当前的问题，参考话术，输出销售回答\n\n这是用户问题：{sys_query}")
                .params(Map.of("sys_query", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode16_text")
                .build();
        stateGraph.addNode("LLMNode16", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode16.apply(state);
                    String key = "LLMNode16_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— CodeNode [1757472828190] ——
        CodeExecutorNodeAction codeNode25 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
def main(arg1, arg2) -> dict:
     keywords = arg1
     budget = arg2
 
     # 安全转换为字符串，防止传入非字符串类型（如 None、数字、dict）调用 .strip() 崩溃
     if budget is None:
         budget_str = ""
     else:
         budget_str = str(budget).strip()
 
     if not budget_str:
         result = f"关键字: {keywords}"
     else:
         result = f"关键字: {keywords} | 销售价格: {budget}"
 
     return {"result": result}

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "LLMNode14_structured_output", "arg2", "LLMNode14_structured_output"))
                .outputKey("codeNode25_output")
                .build();
        stateGraph.addNode("codeNode25", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode25.apply(state);
                    String key = "codeNode25_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode25_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— QuestionClassifierNode [1757495243219] ——
        QuestionClassifierNode questionClassifyNode1 = QuestionClassifierNode.builder()
                .chatClient(chatClient)
                .inputTextKey("startNode1_sys.query")
                .categories(List.of(" 非销售/闲聊（共情类）：用户问题与商品或销售无关，需要共情", "已收集商品信息，需要报价：用户已经明确询问价格。", "销售推进/信息收集：用户有兴趣，但商品信息不完整，需要进一步收集。", "售后类：用户购买后有问题或投诉。"))
                .outputKey("questionClassifyNode1_class_name")
                .classificationInstructions(List.of("请根据输入内容选择对应分类"))
                .build();
        stateGraph.addNode("questionClassifyNode1", AsyncNodeAction.node_async(questionClassifyNode1));

// —— LlmNode [1757507389047] ——
        LlmNode LLMNode17 = LlmNode.builder()
                .systemPromptTemplate("角色设定：{codeNode1_character_design_str}\n你是一名高情商、专业且善于共情的销冠。\n你的目标是与客户建立情感连接，取得客户信任。\n【直接原则】\n当到达以下状态证明已取得了客户信任，你可以根据情况，结束共情，转为销售。\n1、从“你问我答”变为“主动倾诉”\n2、愿意透露更多背景信息\n3、主动询问你的意见和建议\n4、对你个人产生好奇\n5、愿意接受你的下一步安排\n输入信息：\n商家规则：{codeNode3_general_rules_str}\n客户意向商品：{conversation_collect_product_info_str}\n共情话术库参考：{codeNode24_result}")
                .params(Map.of("codeNode3_general_rules_str", "null", "conversation_collect_product_info_str", "null", "codeNode1_character_design_str", "null", "codeNode24_result", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode17_text")
                .build();
        stateGraph.addNode("LLMNode17", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode17.apply(state);
                    String key = "LLMNode17_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— AnswerNode [1757507393796] ——
        AnswerNode answerNode3 = AnswerNode.builder()
                .answer("{{#1757644567098.structured_output.content#}}")
                .outputKey("answerNode3_answer")
                .build();
        stateGraph.addNode("answerNode3", AsyncNodeAction.node_async(answerNode3));

        stateGraph.addEdge("answerNode3", END);
// —— LlmNode [1757644567098] ——
        LlmNode LLMNode18 = LlmNode.builder()
                .systemPromptTemplate("请根据以下要求输出：\n1. 判断销售回复 {LLMNode17_text} 是否包含中文，如果有中文请翻译成英文填入 content，没有中文则直接填写原文。\n2. 根据用户问题 {sys_query} 的内容，判断其属于：\n   - \"继续共情\"：用户仍在表达顾虑、情绪或犹豫，尚未进入购买信号\n   - \"推进销售\"：用户已表现出明确的兴趣、购买意向或接受度，可以进入销售推进阶段\n3. 输出时必须严格符合以下 JSON Schema，只能输出 JSON，不要包含任何多余文字或代码块标记。")
                .params(Map.of("sys_query", "null", "LLMNode17_text", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode18_text")
                .build();
        stateGraph.addNode("LLMNode18", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode18.apply(state);
                    String key = "LLMNode18_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— CodeNode [1757651036593] ——
        CodeExecutorNodeAction codeNode26 = CodeExecutorNodeAction.builder()
                .codeExecutor(codeExecutor)  // 注入的 CodeExecutor Bean
                .codeLanguage("python3")
                .code("""
def main(arg1) -> dict:
  if not arg1 or not isinstance(arg1, list):
      return {"quotableProductNames": []}

  quotable_products = []
  for item in arg1:
      if not isinstance(item, dict):
          continue
      if item.get("isQuotable") == 1:
          product_name = item.get("productName")
          if product_name is not None:
              quotable_products.append(product_name)

  return {"quotableProductNames": quotable_products}

                        """)
                .config(codeExecutionConfig)  // 注入的 CodeExecutionConfig Bean
                .params(Map.of("arg1", "conversation_collect_product_info"))
                .outputKey("codeNode26_output")
                .build();
        stateGraph.addNode("codeNode26", AsyncNodeAction.node_async((state) -> {
                    // 将代码运行的结果拆包
                    Map<String, Object> result = codeNode26.apply(state);
                    String key = "codeNode26_output";
                    Object object = result.get(key);
                    if (!(object instanceof Map)) {
                        return Map.of();
                    }
                    return ((Map<String, Object>) object).entrySet().stream()
                            .collect(Collectors.toMap(
                                    entry -> "codeNode26_" + entry.getKey(),
                                    Map.Entry::getValue
                            ));
                }
        ));

// —— BranchNode [1757657087454] ——
        stateGraph.addNode("branchNode5", AsyncNodeAction.node_async(state -> Map.of()));

// —— LlmNode [1757677324196] ——
        LlmNode LLMNode19 = LlmNode.builder()
                .systemPromptTemplate("请你根据销售阶段逻辑判断客户当前销售阶段\n给出报价话术\n客户当前收集信息：{conversation_collect_product_info_str}")
                .params(Map.of("conversation_collect_product_info_str", "null"))
                .chatClient(chatClient)
                .outputKey("LLMNode19_text")
                .build();
        stateGraph.addNode("LLMNode19", AsyncNodeAction.node_async(state -> {
                    Map<String, Object> result = LLMNode19.apply(state);
                    String key = "LLMNode19_text";
                    Object object = result.get(key);
                    if (object instanceof AssistantMessage && ((AssistantMessage) object).getText() != null) {
                        return Map.of(key, ((AssistantMessage) object).getText());
                    }
                    return Map.of(key, object != null ? object.toString() : "unknown");
                }
        ));

// —— AnswerNode [1757677336096] ——
        AnswerNode answerNode4 = AnswerNode.builder()
                .answer("{LLMNode15_text}")
                .outputKey("answerNode4_answer")
                .build();
        stateGraph.addNode("answerNode4", AsyncNodeAction.node_async(answerNode4));

        stateGraph.addEdge("answerNode4", END);
// —— AnswerNode [1757677341223] ——
        AnswerNode answerNode5 = AnswerNode.builder()
                .answer("{LLMNode19_text}")
                .outputKey("answerNode5_answer")
                .build();
        stateGraph.addNode("answerNode5", AsyncNodeAction.node_async(answerNode5));

        stateGraph.addEdge("answerNode5", END);
// —— BranchNode [1758094979869] ——
        stateGraph.addNode("branchNode6", AsyncNodeAction.node_async(state -> Map.of()));

// —— BranchNode [1758095233679] ——
        stateGraph.addNode("branchNode7", AsyncNodeAction.node_async(state -> Map.of()));


        // add edges
        stateGraph.addEdge("httpNode1", "codeNode1");
        stateGraph.addEdge("httpNode2", "codeNode2");
        stateGraph.addEdge("httpNode3", "codeNode3");
        stateGraph.addEdge("httpNode4", "codeNode4");
        stateGraph.addEdge("httpNode5", "codeNode5");
        stateGraph.addEdge("httpNode8", "LLMNode3");
        stateGraph.addEdge("httpNode7", "codeNode6");
        stateGraph.addEdge("LLMNode3", "codeNode7");
        stateGraph.addEdge("codeNode7", "httpNode9");
        stateGraph.addEdge("LLMNode7", "codeNode10");
        stateGraph.addEdge("codeNode10", "LLMNode6");
        stateGraph.addEdge("codeNode11", "branchNode2");
        stateGraph.addEdge("LLMNode8", "answerNode2");
        stateGraph.addEdge("codeNode1", "branchNode1");
        stateGraph.addEdge("codeNode2", "branchNode1");
        stateGraph.addEdge("codeNode3", "branchNode1");
        stateGraph.addEdge("codeNode4", "branchNode1");
        stateGraph.addEdge("codeNode5", "branchNode1");
        stateGraph.addEdge("codeNode6", "branchNode1");
        stateGraph.addEdge("LLMNode13", "knowledgeRetrievalNode4");
        stateGraph.addEdge("httpNode10", "codeNode12");
        stateGraph.addEdge("codeNode12", "branchNode1");
        stateGraph.addEdge("LLMNode9", "assignerNode3");
        stateGraph.addEdge("LLMNode4", "codeNode9");
        stateGraph.addEdge("codeNode13", "codeNode11");
        stateGraph.addEdge("LLMNode2", "codeNode14");
        stateGraph.addEdge("codeNode14", "httpNode8");
        stateGraph.addEdge("codeNode8", "assignerNode1");
        stateGraph.addEdge("knowledgeRetrievalNode1", "codeNode15");
        stateGraph.addEdge("knowledgeRetrievalNode3", "codeNode16");
        stateGraph.addEdge("knowledgeRetrievalNode2", "codeNode17");
        stateGraph.addEdge("knowledgeRetrievalNode4", "codeNode18");
        stateGraph.addEdge("codeNode16", "LLMNode6");
        stateGraph.addEdge("codeNode17", "LLMNode6");
        stateGraph.addEdge("codeNode18", "LLMNode6");
        stateGraph.addEdge("httpNode6", "LLMNode2");
        stateGraph.addEdge("codeNode15", "LLMNode6");
        stateGraph.addEdge("LLMNode12", "knowledgeRetrievalNode3");
        stateGraph.addEdge("LLMNode10", "knowledgeRetrievalNode1");
        stateGraph.addEdge("LLMNode11", "knowledgeRetrievalNode2");
        stateGraph.addEdge("LLMNode5", "codeNode8");
        stateGraph.addEdge("answerNode2", "httpNode6");
        stateGraph.addEdge("codeNode19", "assignerNode2");
        stateGraph.addEdge("LLMNode1", "codeNode19");
        stateGraph.addEdge("assignerNode4", "LLMNode8");
        stateGraph.addEdge("answerNode1", "branchNode4");
        stateGraph.addEdge("knowledgeRetrievalNode5", "codeNode20");
        stateGraph.addEdge("knowledgeRetrievalNode6", "codeNode21");
        stateGraph.addEdge("codeNode21", "LLMNode15");
        stateGraph.addEdge("knowledgeRetrievalNode7", "codeNode22");
        stateGraph.addEdge("codeNode22", "assignerNode5");
        stateGraph.addEdge("knowledgeRetrievalNode8", "codeNode23");
        stateGraph.addEdge("codeNode23", "LLMNode16");
        stateGraph.addEdge("LLMNode16", "LLMNode6");
        stateGraph.addEdge("codeNode25", "knowledgeRetrievalNode6");
        stateGraph.addEdge("codeNode24", "LLMNode17");
        stateGraph.addEdge("knowledgeRetrievalNode9", "codeNode24");
        stateGraph.addEdge("answerNode3", "branchNode4");
        stateGraph.addEdge("LLMNode17", "LLMNode18");
        stateGraph.addEdge("LLMNode18", "answerNode3");
        stateGraph.addEdge("codeNode26", "branchNode5");
        stateGraph.addEdge("LLMNode6", "codeNode13");
        stateGraph.addEdge("LLMNode14", "codeNode25");
        stateGraph.addEdge("codeNode20", "LLMNode19");
        stateGraph.addEdge("LLMNode15", "answerNode4");
        stateGraph.addEdge("LLMNode19", "answerNode5");
        stateGraph.addEdge("answerNode4", "branchNode4");
        stateGraph.addEdge("answerNode5", "branchNode4");
        stateGraph.addEdge(START, "branchNode6");
        stateGraph.addEdge("codeNode9", "branchNode7");
        stateGraph.addConditionalEdges("branchNode1", edge_async(state -> {
            if ((state.value("unknown", String.class).orElseThrow().equals("0"))) {
                return "7dab09a4-207b-4e71-a9d1-e4a9c1aeee0d";
            }
            if ((state.value("unknown", String.class).orElseThrow().equals("1"))) {
                return "66af82b2-f25b-4369-ab0f-de2a3f2f3e90";
            }
            if ((state.value("unknown", String.class).orElseThrow().equals("开始进行聊天分析"))) {
                return "971d3615-1547-4353-93b4-8e584059f8a5";
            }
            return "false";
        }), Map.of("66af82b2-f25b-4369-ab0f-de2a3f2f3e90", "httpNode6", "971d3615-1547-4353-93b4-8e584059f8a5", "LLMNode2", "7dab09a4-207b-4e71-a9d1-e4a9c1aeee0d", "questionClassifyNode1"));
        stateGraph.addConditionalEdges("branchNode6", edge_async(state -> {
            if (true) {
                return "true";
            }
            return "false";
        }), Map.of("true", "httpNode10"));
        stateGraph.addConditionalEdges("questionClassifyNode1",
                edge_async(state -> {
                    String value = state.value("questionClassifyNode1_class_name", String.class).orElse("");
                    if (value.contains(" 非销售/闲聊（共情类）：用户问题与商品或销售无关，需要共情"))
                        return " 非销售/闲聊（共情类）：用户问题与商品或销售无关，需要共情";
                    if (value.contains("销售推进/信息收集：用户有兴趣，但商品信息不完整，需要进一步收集。"))
                        return "销售推进/信息收集：用户有兴趣，但商品信息不完整，需要进一步收集。";
                    if (value.contains("售后类：用户购买后有问题或投诉。")) return "售后类：用户购买后有问题或投诉。";
                    if (value.contains("已收集商品信息，需要报价：用户已经明确询问价格。"))
                        return "已收集商品信息，需要报价：用户已经明确询问价格。";
                    return "已收集商品信息，需要报价：用户已经明确询问价格。";
                }),
                Map.of(" 非销售/闲聊（共情类）：用户问题与商品或销售无关，需要共情", "knowledgeRetrievalNode7",
                        "销售推进/信息收集：用户有兴趣，但商品信息不完整，需要进一步收集。", "LLMNode4",
                        "售后类：用户购买后有问题或投诉。", "LLMNode4",
                        "已收集商品信息，需要报价：用户已经明确询问价格。", "codeNode26")
        );

        stateGraph.addConditionalEdges("branchNode7", edge_async(state -> {
            if (true) {
                return "true";
            }
            return "false";
        }), Map.of("true", "knowledgeRetrievalNode8"));
        stateGraph.addConditionalEdges("branchNode2", edge_async(state -> {
            if ((state.value("codeNode11_result", String.class).orElseThrow().isEmpty())) {
                return "true";
            }
            return "false";
        }), Map.of("false", "assignerNode4", "true", "answerNode1"));
        stateGraph.addConditionalEdges("branchNode4", edge_async(state -> {
            if (!(state.value("unknown", String.class).orElseThrow().isEmpty())) {
                return "true";
            }
            return "false";
        }), Map.of("true", "httpNode6"));
        stateGraph.addConditionalEdges("branchNode3", edge_async(state -> {
            if (!(state.value("unknown", java.lang.String.class).orElseThrow().isEmpty())) {
                return "true";
            }
            return "false";
        }), Map.of("true", "LLMNode9"));
        stateGraph.addConditionalEdges("branchNode5", edge_async(state -> {
            if (!(state.value("codeNode26_quotableProductNames", java.lang.String.class).orElseThrow().isEmpty())) {
                return "true";
            }
            return "false";
        }), Map.of("true", "LLMNode14", "false", "knowledgeRetrievalNode5"));
        //stateGraph;

        return stateGraph.compile();
    }

    @Bean
    public VectorStore customVectorStore(EmbeddingModel embeddingModel) {
        var chunks = new TokenTextSplitter().transform(new TextReader(ragSource).read());
        SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build();
        vectorStore.write(chunks);
        return vectorStore;
    }

    @Bean
    public Path tempDir() throws IOException {
        // todo： set your work dir
        Path tempDir = Files.createTempDirectory("code-execution-workdir-");
        tempDir.toFile().deleteOnExit();
        return tempDir;
    }

    @Bean
    public CodeExecutionConfig codeExecutionConfig(Path tempDir) {
        return new CodeExecutionConfig().setWorkDir(tempDir.toString());
    }

    @Bean
    public CodeExecutor codeGenerator() {
        return new LocalCommandlineCodeExecutor();
    }
}
